﻿/*
Nombre:                         CategoriaDao
Descripcion:                    Implementacion que maneja las funciones principales sobre el catalogo de categorias manejado en la capa de persistencia 
Dependencias:                 
Fecha de creación:              20080929
Autor:                          VMORALES
Fecha de modifcación:           20090224
Responsable:                  
Num. de modifcación:            2
*/

#region Imports

using Electrocucaracha.AdminPersonal.DAO.Entidades;
using Electrocucaracha.AdminPersonal.DAO.Acciones;
using Common.Logging;
using System;

#endregion

namespace Electrocucaracha.AdminPersonal.DAO
{
    /// <summary>
    /// Implementacion que maneja las funciones principales sobre el catalogo de categorias manejado en la capa de persistencia 
    /// </summary>
    public class CategoriaDao : BaseDao, ICategoriaDao
    {
        #region Constantes

        #endregion

        #region Miembros

        private static readonly ILog log = LogManager.GetLogger(typeof(CategoriaDao));
        private static CategoriaDao instancia = new CategoriaDao();

        #endregion

        #region Propiedades

        /// <summary>
        /// Obtiene la instancia unica para el catalogo de categorias
        /// </summary>
        public static CategoriaDao Instancia
        {
            get
            {
                log.Info("Inicio CategoriaDao.Instancia.get");

                if (instancia == null)
                {
                    instancia = new CategoriaDao();
                }

                log.Info("Fin CategoriaDao.Instancia.get");

                return instancia;
            }
        }//Instancia

        #endregion

        #region Constructores

        private CategoriaDao()
            : base()
        {
            log.Info("Inicio CategoriaDao.ctor()");

            log.Info("Fin CategoriaDao.ctor()");
        }//CategoriaDao

        #endregion

        #region Funciones

        /// <summary>
        /// Funcion que valida si existe una categoria en la capa de persistencia que tenga la misma descripcion
        /// </summary>
        /// <param name="descripcion">Cadena a buscar en la base de datos</param>
        /// <returns>Verdadero en caso de que no exista ninguna categoria</returns>
        private bool Existe(string descripcion)
        {
            log.Info("Inicio CategoriaDao.Existe(string descripcion)");

            log.Debug("Descripcion a buscar : " + descripcion);
            bool respuesta = this.ObtenerPorDescripcion(descripcion) != null;
            log.Debug("Existe categoria por descripcion : " + respuesta);

            log.Info("Fin CategoriaDao.Existe(string descripcion)");

            return respuesta;
        }//Existe

        #endregion

        #region IGenericoDao

        /// <summary>
        /// Funcion que agrega un objeto de tipo categoria a la capa de persistencia
        /// </summary>
        /// <param name="categoria">Objeto a ser agregado a la capa de persistencia</param>
        /// <returns>Verdadero en caso de exito en la insercion del objeto falso en caso contrario</returns>
        public bool Agregar(ref CategoriaDTO categoria)
        {
            log.Info("Inicio CategoriaDao.Agregar(ref CategoriaDTO categoria)");

            //Validacion de parametros
            Validar(categoria, Validaciones.Nulo | Validaciones.DescripcionVacia);

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.AGREGAR);
            log.Debug("Accion : " + accion);
            accion.Parametros[Accion.INPUT] = categoria;
            accion.Parametros[Accion.OUTPUT] = false;

            //Se compara solo su descripcion ya que no se el identificador carece de importancia
            if (!this.Existe(categoria.Descripcion))
            {
                log.Info("Insercion de la categoria");
                admin.Ejecutar(accion);
            }

            log.Info("Fin CategoriaDao.Agregar(ref CategoriaDTO categoria)");

            return (bool)accion.Parametros[Accion.OUTPUT];
        }//Agregar

        /// <summary>
        /// Funcion que agrega un conjunto de objetos de tipo categoria a la capa de persistencia
        /// </summary>
        /// <param name="categorias">Conjunto de objetos de tipo categoria a ser agregados</param>
        /// <returns>El indice de la ultima categoria la cual fue agregada con exito a la capa de persistencia</returns>
        public int Agregar(ref CategoriaDTO[] categorias)
        {
            log.Info("Inicio CategoriaDao.Agregar(ref Categoria[] categorias)");

            //Validacion de datos
            Validar(categorias, Validaciones.Nulo & Validaciones.DescripcionVacia);

            int i = 0;
            for (; i < categorias.Length; i++)
            {
                if (!Agregar(ref categorias[i]))
                {
                    log.Error("No se pudo agregar la categoria con la descripcion : " + categorias[i].Descripcion);
                    break;
                }
            }

            log.Info("Fin CategoriaDao.Agregar(ref Categoria[] categorias)");

            return i;
        }//Agregar

        /// <summary>
        /// Funcion que elimina(en caso de existir) un objeto de tipo categoria de la capa de persistencia
        /// </summary>
        /// <param name="categoria">Objeto a ser eliminado</param>
        /// <returns>Verdadero en caso de eliminacion falso en caso contrario</returns>
        public bool Eliminar(CategoriaDTO categoria)
        {
            log.Info("Inicio CategoriaDao.Eliminar(CategoriaDTO categoria)");

            //Validacion de parametros
            if (!Existe(categoria))
            {
                log.Error("No existe la categoria a eliminar");
                throw new DAOException("No existe la categoria a eliminar");
            }

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.ELIMINAR);
            log.Debug("Accion : " + accion);
            accion.Parametros[Accion.INPUT] = categoria;
            admin.Ejecutar(accion);

            log.Info("Fin CategoriaDao.Eliminar(CategoriaDTO categoria)");

            return (bool)accion.Parametros[Accion.OUTPUT];
        }//Eliminar

        /// <summary>
        /// Funcion que elimina(en caso de existir) un conjunto de objetos de tipo categoria de la capa de persistencia
        /// </summary>
        /// <param name="categoria">Conjunto de objetos a ser eliminados</param>
        /// <returns>El indice de la ultima categoria la cual fue eliminada con exito a la capa de persistencia</returns>
        public int Eliminar(CategoriaDTO[] categorias)
        {
            log.Info("Inicio CategoriaDao.Eliminar(Categoria[] categorias)");

            int i = 0;
            for (; i < categorias.Length; i++)
            {
                if (!Eliminar(categorias[i]))
                {
                    log.Error("No se pudo eliminar la categoria con la descripcion : " + categorias[i].Descripcion);
                    break;
                }
            }

            log.Info("Fin CategoriaDao.Eliminar(Categoria[] categorias)");

            return i;
        }//Eliminar

        /// <summary>
        /// Funcion que obtiene una categoria, de la capa de persistencia, a partir de su identificador
        /// </summary>
        /// <param name="id">Identificador de la categoria a obtener</param>
        /// <returns>Una categoria en caso de encontrarlo nulo en caso contrario</returns>
        public CategoriaDTO Obtener(int id)
        {
            log.Info("Inicio CategoriaDao.Obtener(int id)");
            //Validacion de parametros
            if (id < -1)
            {
                log.Error("No existen categorias con identificadores negativos");
                throw new DAOException("No existen categorias con identificadores negativos");
            }

            CategoriaDTO resultado = null;
            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER);
            accion.Parametros[Accion.INPUT] = id;
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);
            resultado = accion.Parametros[Accion.OUTPUT] as CategoriaDTO;

            log.Info("Fin CategoriaDao.Obtener(int id)");

            return resultado;
        }//Obtener

        /// <summary>
        /// Funcion que devuelve todas las categorias registradas en la capa de persistencia
        /// </summary>
        /// <returns>Conjunto de categorias</returns>
        public CategoriaDTO[] Obtener()
        {
            log.Info("Inicio CategoriaDao.Obtener()");

            CategoriaDTO[] resultado = null;
            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER_TODOS);
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);
            resultado = accion.Parametros[Accion.OUTPUT] as CategoriaDTO[];

            if (resultado != null && resultado.Length == 0)
            {
                log.Warn("Reseteando el valor obtenido");
                resultado = null;
            }

            log.Info("Fin CategoriaDao.Obtener()");

            return resultado;
        }//Obtener

        /// <summary>
        /// Funcion que actualiza en la capa de persistencia el objeto solicitado
        /// </summary>
        /// <param name="categoria">Objeto a ser actualizado en la capa de persistencia</param>
        /// <returns>Verdadero en caso de exito falso en caso contrario</returns>
        public bool Actualizar(CategoriaDTO categoria)
        {
            log.Info("Inicio CategoriaDao.Actualizar(CategoriaDTO categoria)");

            //Validacion de parametros
            Validar(categoria, Validaciones.Nulo | Validaciones.IdentificadorNegativo);
            if (!Existe(categoria))
            {
                log.Error("No existe la categoria a actualizar");
                throw new DAOException("No existe la categoria a actualizar");
            }

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.ACTUALIZAR);
            log.Debug("Accion : " + accion);
            accion.Parametros[Accion.INPUT] = categoria;
            admin.Ejecutar(accion);

            log.Info("Fin CategoriaDao.Actualizar(CategoriaDTO categoria)");

            return (bool)accion.Parametros[Accion.OUTPUT];
        }//Actualizar

        /// <summary>
        /// Funcion que actualiza en la capa de persistencia un conjunto de categorias
        /// </summary>
        /// <param name="categorias">Conjunto de categorias a actualizar en la capa de persistencia</param>
        /// <returns>El indice de la ultima categoria la cual fue actualizada con exito a la capa de persistencia</returns>
        public int Actualizar(CategoriaDTO[] categorias)
        {
            log.Info("Inicio CategoriaDao.Actualizar(Categoria[] categorias)");

            //Validacion de datos
            Validar(categorias, Validaciones.Nulo & Validaciones.IdentificadorNegativo);

            int i = 0;
            for (; i < categorias.Length; i++)
            {
                if (!Actualizar(categorias[i]))
                {
                    log.Error("No se pudo actualizar la categoria con id : " + categorias[i].Id);
                    break;
                }
            }

            log.Info("Fin CategoriaDao.Actualizar(Categoria[] categorias)");

            return i;
        }//Actualizar

        /// <summary>
        /// Funcion que determina si el objeto actualmente se encuentra registrado en la capa de persistencia
        /// </summary>
        /// <param name="categoria">Objeto a validar su existencia</param>
        /// <returns>Verdadero en caso de existir falso en caso contrario</returns>
        public bool Existe(CategoriaDTO categoria)
        {
            log.Info("Inicio CategoriaDao.Existe(CategoriaDTO categoria)");

            //Validacion de datos
            Validar(categoria, Validaciones.Nulo);

            bool existe = this.Obtener(categoria.Id) != null; 
            log.Debug("Busqueda por id : " + existe);

            log.Info("Fin CategoriaDao.Existe(CategoriaDTO categoria)");

            return existe;
        }//Existe

        /// <summary>
        /// Funcion que devuelve la cantidad de categorias registradas en la capa de persistencia
        /// </summary>
        /// <returns>Cantidad de categorias registradas</returns>
        public int ObtenerCantidad()
        {
            log.Info("Inicio CategoriaDao.ObtenerCantidad()");

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER_CANTIDAD);
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);

            log.Info("Fin CategoriaDao.ObtenerCantidad()");

            return (int)accion.Parametros[Accion.OUTPUT];
        }//ObtenerCantidad

        /// <summary>
        /// Funcion que resetea el identificador del catalogo de categorias al menor registrado en la tabla
        /// </summary>
        public void ResetearId()
        {
            log.Info("Inicio CategoriaDao.ResetearId()");

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.RESETEAR_ID);
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);

            log.Info("Fin CategoriaDao.ResetearId()");
        }//ResetearId

        /// <summary>
        /// Funcion que valida los campos correctos del objeto
        /// </summary>
        /// <param name="categoria">Objeto a ser validado</param>
        /// <param name="validacion">Opciones de validacion de los campos</param>
        public void Validar(CategoriaDTO categoria, Validaciones validacion)
        {
            log.Info("Inicio CategoriaDao.Validar(CategoriaDTO categoria, Validaciones validacion)");

            if ((validacion & Validaciones.Nulo) == Validaciones.Nulo)
            {
                log.Debug("Validacion de objeto nulo");
                if (categoria == null)
                {
                    log.Error("El objeto es nulo");
                    throw new DAOException("El objeto es nulo");
                }
            }

            if ((validacion & Validaciones.DescripcionVacia) == Validaciones.DescripcionVacia)
            {
                log.Debug("Validacion de descripcion vacia");
                if (string.IsNullOrEmpty(categoria.Descripcion))
                {
                    log.Error("La categoria no tiene descripcion alguna");
                    throw new DAOException("La categoria no tiene descripcion alguna");
                }
            }

            if ((validacion & Validaciones.IdentificadorNegativo) == Validaciones.IdentificadorNegativo)
            {
                log.Debug("Validacion de identificador negativo");
                if (categoria.Id < 0)
                {
                    log.Error("La categoria no puede tener un identificador negativo");
                    throw new DAOException("La categoria no puede tener un identificador negativo");
                }
            }

            log.Info("Fin CategoriaDao.Validar(CategoriaDTO categoria, Validaciones validacion)");
        }//Validar

        /// <summary>
        /// Funcion que valida cada uno de los elementos de un conjunto de categorias
        /// </summary>
        /// <param name="categorias">Conjunto de categorias a ser validadas</param>
        /// /// <param name="validacion">Opcion de validacion de campos</param>
        public void Validar(CategoriaDTO[] categorias, Validaciones validacion)
        {
            log.Info("Inicio CategoriaDao.Validar(CategoriaDTO[] categorias, Validaciones validacion)");

            if (categorias == null)
            {
                log.Error("El objeto es nulo");
                throw new DAOException("El objeto es nulo");
            }

            foreach (CategoriaDTO c in categorias)
            {
                Validar(c, validacion);
            }

            log.Info("Fin CategoriaDao.Validar(CategoriaDTO[] categorias, Validaciones validacion)");
        }//Validar

        #endregion

        #region ICatalogo

        /// <summary>
        /// Funcion que obtiene todas las categorias que concidan con la descripcion solicitada
        /// </summary>
        /// <param name="descripcion">Descripcion a buscar en la capa de persistencia</param>
        /// <returns>Conjunto de objetos que comparten la misma descripcion</returns>
        public CategoriaDTO[] ObtenerPorDescripcion(string descripcion)
        {
            log.Info("Inicio CategoriaDao.ObtenerPorDescripcion(string descripcion)");

            CategoriaDTO[] resultado = null;
            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER_POR_DESCRIPCION);
            log.Debug("Accion : " + accion);
            accion.Parametros[Accion.INPUT] = descripcion;
            admin.Ejecutar(accion);
            resultado = accion.Parametros[Accion.OUTPUT] as CategoriaDTO[];

            if (resultado != null && resultado.Length == 0)
            {
                log.Warn("Reseteando el valor obtenido");
                resultado = null;
            }

            log.Info("Fin CategoriaDao.ObtenerPorDescripcion(string descripcion)");

            return resultado;
        }//ObtenerPorDescripcion

        /// <summary>
        /// Funcion que obtiene todas las categorias que tengan en su descripcion el parametro solicitado
        /// </summary>
        /// <param name="descripcion">Descripcion a contener en las descripciones de los objetos</param>
        /// <returns>Conjunto de objetos que incluyen en su descripcion en parametro deseado</returns>
        public CategoriaDTO[] ObtenerPorDescripcionSimilar(string descripcion)
        {
            log.Info("Inicio CategoriaDao.ObtenerPorDescripcionSimilar(string descripcion)");

            CategoriaDTO[] resultado = null;
            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER_POR_DESCRIPCION_SIMILAR);
            accion.Parametros[Accion.INPUT] = descripcion;
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);
            resultado = accion.Parametros[Accion.OUTPUT] as CategoriaDTO[];

            if (resultado != null && resultado.Length == 0)
            {
                log.Warn("Reseteando el valor obtenido");
                resultado = null;
            }

            log.Info("Fin CategoriaDao.ObtenerPorDescripcionSimilar(string descripcion)");

            return resultado;
        }//ObtenerPorDescripcionSimilar

        #endregion

        #region IActivo

        /// <summary>
        /// Funcion que devuelve todos los objetos con estatus de activo de la capa de persistencia
        /// </summary>
        /// <returns>Conjunto de objetos con el mismo estatus de activo</returns>
        public CategoriaDTO[] ObtenerActivos()
        {
            log.Info("Inicio CategoriaDao.ObtenerActivos()");

            CategoriaDTO[] resultado = null;
            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER_ACTIVOS);
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);
            resultado = accion.Parametros[Accion.OUTPUT] as CategoriaDTO[];

            if (resultado != null && resultado.Length == 0)
            {
                log.Warn("Reseteando el valor obtenido");
                resultado = null;
            }

            log.Info("Fin CategoriaDao.ObtenerActivos()");

            return resultado;
        }//ObtenerActivos

        /// <summary>
        /// Funcion que devuelve todos los objetos con estatus de inactivo de la capa de persistencia
        /// </summary>
        /// <returns>Conjunto de objetos con el mismo estatus de inactivo</returns>
        public CategoriaDTO[] ObtenerInactivos()
        {
            log.Info("Inicio CategoriaDao.ObtenerInactivos()");

            CategoriaDTO[] resultado = null;
            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.OBTENER_INACTIVOS);
            log.Debug("Accion : " + accion);
            admin.Ejecutar(accion);
            resultado = accion.Parametros[Accion.OUTPUT] as CategoriaDTO[];

            if (resultado != null && resultado.Length == 0)
            {
                log.Warn("Reseteando el valor obtenido");
                resultado = null;
            }

            log.Info("Fin CategoriaDao.ObtenerInactivos()");

            return resultado;
        }//ObtenerInactivos

        /// <summary>
        /// Funcion que actualiza el estatus a activo de la categoria en la capa de persistencia
        /// </summary>
        /// <param name="categoriaInactiva">Objeto con el estatus a actualizar</param>
        /// <returns>Verdadero en caso de exito falso en caso contrario</returns>
        public bool Activar(CategoriaDTO categoriaInactiva)
        {
            log.Info("Inicio CategoriaDao.Activar(Categoria categoriaInactiva)");

            if (!Existe(categoriaInactiva))
            {
                log.Error("No existe la categoria a activar");
                throw new DAOException("No existe la categoria a activar");
            }

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.ACTIVAR);
            log.Debug("Accion : " + accion);
            bool respuesta = false;
            accion.Parametros[Accion.INPUT] = categoriaInactiva;

            admin.Ejecutar(accion);
            respuesta = (bool)accion.Parametros[Accion.OUTPUT];
            categoriaInactiva.Activo = respuesta ? true : categoriaInactiva.Activo;

            log.Info("Fin CategoriaDao.Activar(Categoria categoriaInactiva)");

            return respuesta;
        }//Activar

        /// <summary>
        /// Funcion que actualiza el estatus a desactivo de la categoria en la capa de persistencia
        /// </summary>
        /// <param name="categoriaActiva">Objeto con el estatus a actualizar</param>
        /// <returns>Verdadero en caso de exito falso en caso contrario</returns>
        public bool Desactivar(CategoriaDTO categoriaActiva)
        {
            log.Info("Inicio CategoriaDao.Desactivar(Categoria categoriaActiva)");

            if (!Existe(categoriaActiva))
            {
                log.Error("No existe la categoria a activar");
                throw new DAOException("No existe la categoria a desactivar");
            }

            Accion accion = admin.ObtenerAccion(CatalogoAcciones.Categoria.DESACTIVAR);
            log.Debug("Accion : " + accion);
            bool respuesta = false;
            accion.Parametros[Accion.INPUT] = categoriaActiva;

            admin.Ejecutar(accion);
            respuesta = (bool)accion.Parametros[Accion.OUTPUT];
            categoriaActiva.Activo = respuesta ? false : categoriaActiva.Activo;

            log.Info("Fin CategoriaDao.Desactivar(Categoria categoriaActiva)");

            return respuesta;
        }//Desactivar

        #endregion
    }//CategoriaDao
}//Electrocucaracha.AdminPersonal.DAO